package nbcp

import org.synchronoss.cloud.nio.multipart.MultipartUtils.getHeaders
import org.springframework.cloud.gateway.filter.GatewayFilterChain
import org.springframework.web.server.ServerWebExchange
import reactor.core.publisher.Mono
import org.springframework.core.Ordered
import org.springframework.cloud.gateway.filter.GlobalFilter
import org.springframework.http.HttpStatus
import org.springframework.http.server.ServerHttpRequest
import org.springframework.http.server.reactive.ServerHttpResponse
import reactor.function.TupleUtils.predicate
import reactor.core.publisher.Flux
import org.synchronoss.cloud.nio.multipart.MultipartUtils.getHeaders
import java.io.IOException
import org.reactivestreams.Publisher
import org.slf4j.LoggerFactory
import org.springframework.cloud.gateway.filter.GatewayFilter
import org.springframework.core.io.buffer.DataBuffer
import org.springframework.http.MediaType
import java.util.function.BiFunction
import org.springframework.http.server.reactive.ServerHttpResponseDecorator
import java.nio.charset.Charset


/**
 * Created by yuxh on 2019/4/28
 */


class AuthorizationFilter : GlobalFilter, Ordered {
    companion object {
        private val logger = LoggerFactory.getLogger(this::class.java.declaringClass)
    }

    override fun getOrder(): Int {
        return -100;
    }

    override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {
        var request = exchange.request
        var response = exchange.response;

        var path = request.uri.rawPath.toString()
        logger.warn(path)

        if (path == "/hi") {
            response.statusCode = HttpStatus.OK
            response.headers.contentType = MediaType.APPLICATION_JSON_UTF8
            var jsonString = """{"msg":""}"""
            return response.writeJsonString(jsonString, exchange, chain)

//            response.bufferFactory().wrap(jsonString.toByteArray())
//            return response.setComplete();
        }
        return chain.filter(exchange)
//        val buffer = response.bufferFactory().wrap(byteArrayOf())
//        return exchange.response.writeWith(Flux.just(buffer))
//        return chain.filter(exchange)
    }
}


private fun ServerHttpResponse.writeJsonString(jsonString: String, exchange: ServerWebExchange, chain: GatewayFilterChain): Mono<Void> {

    val decoratedResponse = object : ServerHttpResponseDecorator(exchange.response) {
        override fun writeWith(body: Publisher<out DataBuffer>): Mono<Void> {
            if (body is Flux<*>) {

                val fluxBody = body as Flux<out DataBuffer>
                return super.writeWith(fluxBody.map { dataBuffer ->
                    // probably should reuse buffers
//                    val content = ByteArray(dataBuffer.readableByteCount())
//                    dataBuffer.read(content)
//                    val content_value = String(content, Charset.forName("UTF-8"));

                    val uppedContent = jsonString.toByteArray()
                    exchange.response.bufferFactory().wrap(uppedContent)
                })
            }
            return super.writeWith(body) // if body is not a flux. never got there.
        }
    }

    return chain.filter(exchange.mutate().response(decoratedResponse).build())
}
